package club.cearnach.api.service.impl;

import club.cearnach.api.dao.IRoleDao;
import club.cearnach.api.dao.IUserDao;
import club.cearnach.entity.Role;
import club.cearnach.entity.User;
import club.cearnach.api.exception.RoleNotFoundException;
import club.cearnach.api.exception.UserException;
import club.cearnach.api.form.PageBean;
import club.cearnach.api.service.IUserService;
import club.cearnach.security.enumeration.RoleEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;
import java.util.Optional;


/**
 * @author 阮胜
 * @date 2018/5/26 14:26
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class UserServiceImpl implements IUserService {
    private final IUserDao userDao;
    private final IRoleDao roleDao;

    public UserServiceImpl(IUserDao userDao, IRoleDao roleDao) {
        this.userDao = userDao;
        this.roleDao = roleDao;
    }


    @Override
    public void delete(Integer id) throws UserException {
        userDao.findById(id).orElseThrow(() -> new UserException(UserException.USER_CAN_NOT_FOUNT));
        userDao.deleteById(id);
    }

    @Override
    public User save(User user) {
        if (StringUtils.isEmpty(user.getNickname())) {
            user.setNickname("电影用户");
        }
        log.info("Save user account = {} , password ={}", user.getAccount(), user.getPassword());
        return userDao.save(user);
    }

    @Override
    public User find(String account, String password) throws UserException {
        return userDao.findByAccountAndPassword(account, password).orElseThrow(() -> new UserException(UserException.USER_CAN_NOT_FOUNT));
    }

    @Override
    public Optional<User> findByAccount(String account) {
        return userDao.findByAccount(account);
    }

    @Override
    public Optional<User> findByAccountAndPrivilege(String account, RoleEnum roleEnum) throws RoleNotFoundException {
        Role role = roleDao.findByName(roleEnum.getRole()).orElseThrow(RoleNotFoundException::new);
        return userDao.findByAccountAndRoleId(account, role.getId());
    }

    @Override
    public User find(Integer id) throws UserException {
        return userDao.findById(id).orElseThrow(() -> new UserException(UserException.USER_CAN_NOT_FOUNT));
    }

    @Override
    public User find(User user) throws UserException {
        return userDao.findByAccountAndPassword(user.getAccount(), user.getPassword()).orElseThrow(() -> new UserException(UserException.USER_CAN_NOT_FOUNT));
    }

    @Override
    public Page<User> findAllOrderByCreateDate(PageBean pageBean) {
        return userDao.findAll(PageRequest.of(pageBean.getPage(), pageBean.getSize(), Sort.by(Sort.Direction.DESC, "createDate")));
    }

    @Override
    public Page<User> findAll(Pageable pageable) {
        return userDao.findAll(pageable);
    }

    @Override
    public Page<User> findByLastLoginDate() {
        return findAll(PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "lastLoginDate")));
    }

    @Override
    public List<User> findByIdIn(Integer... ids) {
        if (ids != null && ids.length > 0) {
            return userDao.findByIdIn(ids);
        }
        return null;
    }

    @Override
    public void deleteIn(Integer... ids) {
        for (Integer id : ids) {
            try {
                delete(id);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }

    @Override
    public long count() {
        return userDao.count();
    }

    @Override
    public boolean isExist(String account, Integer id) {
        return id == null || id == 0
                ? userDao.findByAccount(account).isPresent()
                : userDao.findByAccountAndIdNot(account, id).isPresent();
    }

    @Override
    public Optional<User> login(String account, String pwd) {
        Optional<User> userOptional = userDao.findByAccountAndPassword(account, pwd);
        userOptional.ifPresent(user -> {
            user.setLastLoginDate(new Date());
            userDao.save(user);
        });
        return userOptional;
    }

    @Override
    public Optional<User> findByAccountAndEmail(String account,String email) {
        return userDao.findByAccountAndEmail(account, email);
    }

}
